﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace SMTPClient
{
    public class SMTP
    {
        private string username;
        private string password;
        private string usernameId;
        private string userServer;

        public SMTP(string username, string password)
        {
            this.username = username;
            this.password = password;
            string[] usernameParts = username.Split('@');
            if (usernameParts.Length == 1)// 说明不含@
            {
                throw new Exception("邮箱地址必须完整");
            }
            else
            {
                this.usernameId = usernameParts[0];
                this.userServer = usernameParts[1];
            }
        }

        public SMTP()
        {
            this.username = "";
            this.password = "";
            this.usernameId = "";
            this.userServer = "";
        }


        public void CheckRes(string head, string s)
        {
            if(s == null || s == "")
            {
                throw new Exception(head + "SMTP服务器无响应");
            }
            string[] groups = s.Split(" ");
            string num = groups[0];
            switch (num)
            {
                case "421":
                    throw new Exception(head + "服务未就绪，关闭传输信道");
                    break;
                case "450":
                    throw new Exception(head + "要求的邮件操作未完成，邮箱不可用");
                    break;
                case "451":
                    throw new Exception(head + "放弃要求的操作；处理过程中出错");
                    break;
                case "452":
                    throw new Exception(head + "系统存储不足，要求的操作未执行");
                    break;
                case "501":
                    throw new Exception(head + "参数格式错误");
                    break;
                case "502":
                    throw new Exception(head + "命令不可实现");
                    break;
                case "503":
                    throw new Exception(head + "错误的命令序列");
                    break;
                case "504":
                    throw new Exception(head + "命令参数不可实现");
                    break;
                case "550":
                    throw new Exception(head + "要求的邮件操作未完成，邮箱不可用");
                    break;
                case "551":
                    throw new Exception(head + "用户非本地");
                    break;
                case "552":
                    throw new Exception(head + "过量的存储分配，要求的操作未执行");
                    break;
                case "553":
                    throw new Exception(head + "邮箱名不可用，要求的操作未执行");
                    break;
                case "554":
                    throw new Exception(head + "操作失败");
                    break;
                default:
                    break;
            }
        }
        public void SendMail(string receiveUsername, string data, string title)
        {
            string base64Username = Convert.ToBase64String(Encoding.ASCII.GetBytes(username));
            string base64Password = Convert.ToBase64String(Encoding.ASCII.GetBytes(password));

            //using (TcpClient client = new TcpClient("smtp.163.com", 25))
            using (TcpClient client = new TcpClient("smtp." + userServer, 25))
            {
                // 创建socket
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                IPEndPoint remoteEndPoint = (IPEndPoint)client.Client.RemoteEndPoint;
                socket.Connect(remoteEndPoint);
                Console.WriteLine("连接服务器成功");

                // 连接服务器成功后，开始执行协议内容
                using (NetworkStream stream = new NetworkStream(socket))
                {
                    using (StreamReader reader = new StreamReader(stream, Encoding.ASCII))
                    using (StreamWriter writer = new StreamWriter(stream, Encoding.ASCII))
                    {
                        string res = reader.ReadLine();
                        CheckRes("连接SMTP服务器错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应

                        // 发送 'helo' 命令

                        writer.WriteLine("helo smtp");
                        writer.Flush(); // 强行更新
                        res = reader.ReadLine();
                        CheckRes("声明客户端主机名错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("helo成功！");

                        // 发送 'auth login' 命令

                        writer.WriteLine("auth login");
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("安全认证错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("auth login成功！");


                        // 发送用户名（经过Base64编码）

                        writer.WriteLine(base64Username);
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("发送用户名错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("发送用户名成功！");

                        // 发送授权码（经过Base64编码）

                        writer.WriteLine(base64Password);
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("用户认证错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("发送密码（授权码）成功！");

                        // 设置发件人和收件人

                        writer.WriteLine("MAIL FROM: <" + username + ">");
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("设置发件人错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("设置发件人成功！");


                        writer.WriteLine("RCPT TO: <" + receiveUsername + ">");
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("设置收件人错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("设置收件人成功！");

                        // 设置邮件内容

                        writer.WriteLine("DATA");
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("设置邮件内容错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("设置内容成功！");


                        // 发送邮件内容

                        writer.WriteLine("Subject:" + title);
                        writer.WriteLine("From:" + username);
                        writer.WriteLine("To:" + receiveUsername);
                        // writer.WriteLine("Content-Type: text/plain;charset=\"utf-8\"");
                        writer.WriteLine("Content-Type: text/html; charset=UTF-8");
                        writer.WriteLine();
                        writer.WriteLine(data);
                        writer.WriteLine(".");
                        writer.WriteLine();
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("发送邮件错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("发送成功！");


                        // 发送 'quit' 命令终止会话

                        writer.WriteLine("quit");
                        writer.Flush();
                        res = reader.ReadLine();
                        CheckRes("结束SMTP会话错误： ", res);
                        Console.WriteLine(res); // 读取服务器响应
                        Console.WriteLine("终止成功！");
                    }
                }
                socket.Close();
            }
        }
    }
}
